home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / comms / non-internet / samba / source / locking.c < prev    next >
C/C++ Source or Header  |  1996-06-26  |  8KB  |  331 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    Locking functions
  5.    Copyright (C) Andrew Tridgell 1992-1995
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #include "includes.h"
  23. #include "loadparm.h"
  24. extern int DEBUGLEVEL;
  25. extern connection_struct Connections[];
  26. extern files_struct Files[];
  27.  
  28. pstring share_del_pending="";
  29.  
  30.  
  31. /****************************************************************************
  32.   utility function called to see if a file region is locked
  33. ****************************************************************************/
  34. BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset)
  35. {
  36.   int snum = SNUM(cnum);
  37.  
  38.   if (count == 0)
  39.     return(False);
  40.  
  41.   if (!lp_locking(snum) || !lp_strict_locking(snum))
  42.     return(False);
  43.  
  44.   return(fcntl_lock(Files[fnum].fd,F_GETLK,offset,count,
  45.             (Files[fnum].can_write?F_WRLCK:F_RDLCK)));
  46. }
  47.  
  48.  
  49. /****************************************************************************
  50.   utility function called by locking requests
  51. ****************************************************************************/
  52. BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
  53. {
  54.   BOOL ok = False;
  55.  
  56.   if (!lp_locking(SNUM(cnum)))
  57.     return(True);
  58.  
  59.   if (count == 0) {
  60.     *eclass = ERRDOS;
  61.     *ecode = ERRnoaccess;
  62.     return False;
  63.   }
  64.  
  65.   if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  66.     ok = fcntl_lock(Files[fnum].fd,F_SETLK,offset,count,
  67.             (Files[fnum].can_write?F_WRLCK:F_RDLCK));
  68.  
  69.   if (!ok) {
  70.     *eclass = ERRDOS;
  71.     *ecode = ERRlock;
  72.     return False;
  73.   }
  74.   return True; /* Got lock */
  75. }
  76.  
  77.  
  78. /****************************************************************************
  79.   utility function called by unlocking requests
  80. ****************************************************************************/
  81. BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
  82. {
  83.   BOOL ok = False;
  84.  
  85.   if (!lp_locking(SNUM(cnum)))
  86.     return(True);
  87.  
  88.   if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  89.     ok = fcntl_lock(Files[fnum].fd,F_SETLK,offset,count,F_UNLCK);
  90.    
  91.   if (!ok) {
  92.     *eclass = ERRDOS;
  93.     *ecode = ERRlock;
  94.     return False;
  95.   }
  96.   return True; /* Did unlock */
  97. }
  98.  
  99. /*******************************************************************
  100.   name a share file
  101.   ******************************************************************/
  102. static BOOL share_name(int cnum,struct stat *st,char *name)
  103. {
  104.   strcpy(name,lp_lockdir());
  105.   standard_sub(cnum,name);
  106.   trim_string(name,"","/");
  107.   if (!*name) return(False);
  108.   name += strlen(name);
  109.   
  110.   sprintf(name,"/share.%d.%d",(int)st->st_dev,(int)st->st_ino);
  111.   return(True);
  112. }
  113.  
  114. /*******************************************************************
  115.   use the fnum to get the share file name
  116.   ******************************************************************/
  117. static BOOL share_name_fnum(int fnum,char *name)
  118. {
  119.   struct stat st;
  120.   if (fstat(Files[fnum].fd,&st) != 0) return(False);
  121.   return(share_name(Files[fnum].cnum,&st,name));
  122. }
  123.  
  124.  
  125. /*******************************************************************
  126.   get the share mode of a file using the fnum
  127.   ******************************************************************/
  128. int get_share_mode_by_fnum(int cnum,int fnum,int *pid)
  129. {
  130.   struct stat sbuf;
  131.   if (fstat(Files[fnum].fd,&sbuf) == -1) return(0);
  132.   return(get_share_mode(cnum,&sbuf,pid));
  133. }
  134.  
  135. /*******************************************************************
  136.   get the share mode of a file using the files name
  137.   ******************************************************************/
  138. int get_share_mode_byname(int cnum,char *fname,int *pid)
  139. {
  140.   struct stat sbuf;
  141.   if (stat(fname,&sbuf) == -1) return(0);
  142.   return(get_share_mode(cnum,&sbuf,pid));
  143. }  
  144.  
  145.  
  146. /*******************************************************************
  147. get the share mode of a file
  148. ********************************************************************/
  149. int get_share_mode(int cnum,struct stat *sbuf,int *pid)
  150. {
  151.   pstring fname;
  152.   int fd2;
  153.   char buf[16];
  154.   int ret;
  155.   time_t t;
  156.  
  157.   *pid = 0;
  158.  
  159.   if (!share_name(cnum,sbuf,fname)) return(0);
  160.  
  161.   fd2 = open(fname,O_RDONLY,0);
  162.   if (fd2 < 0) return(0);
  163.  
  164.   if (read(fd2,buf,16) != 16) {
  165.     close(fd2);
  166.     unlink(fname);
  167.     return(0);
  168.   }
  169.   close(fd2);
  170.  
  171.   t = IVAL(buf,0);
  172.   ret = IVAL(buf,4);
  173.   *pid = IVAL(buf,8);
  174.   
  175.   if (IVAL(buf,12) != LOCKING_VERSION) {    
  176.     if (!unlink(fname)) DEBUG(2,("Deleted old locking file %s",fname));
  177.     *pid = 0;
  178.     return(0);
  179.   }
  180.  
  181.   if (*pid && !process_exists(*pid)) {
  182.     ret=0;
  183.     *pid = 0;
  184.   }
  185.  
  186.   if (! *pid) unlink(fname); /* XXXXX race, race */
  187.  
  188.   if (*pid)
  189.     DEBUG(5,("Read share file %s mode 0x%X pid=%d\n",fname,ret,*pid));
  190.  
  191.   return(ret);
  192. }
  193.  
  194.  
  195. /*******************************************************************
  196. del the share mode of a file, if we set it last
  197. ********************************************************************/
  198. void del_share_mode(int fnum)
  199. {
  200.   pstring fname;
  201.   int fd2;
  202.   char buf[16];
  203.   time_t t=0;
  204.   int pid=0;
  205.   BOOL del = False;
  206.  
  207.   if (!share_name_fnum(fnum,fname)) return;
  208.  
  209.   fd2 = open(fname,O_RDONLY,0);
  210.   if (fd2 < 0) return;
  211.   if (read(fd2,buf,16) != 16)
  212.     del = True;
  213.   close(fd2);
  214.  
  215.   if (!del) {
  216.     t = IVAL(buf,0);
  217.     pid = IVAL(buf,8);
  218.   }
  219.  
  220.   if (!del)
  221.     if (IVAL(buf,12) != LOCKING_VERSION || !pid || !process_exists(pid))
  222.       del = True;
  223.  
  224.   if (!del && t == Files[fnum].open_time && pid==(int)getpid())
  225.     del = True;
  226.  
  227.   if (del) {
  228.     if (!unlink(fname)) 
  229.       DEBUG(2,("Deleted share file %s\n",fname));
  230.     else {
  231.       DEBUG(3,("Pending delete share file %s\n",fname));
  232.       if (*share_del_pending) DEBUG(0,("Share del clash!\n"));
  233.       strcpy(share_del_pending,fname);
  234.     }
  235.   }
  236. }
  237.   
  238.  
  239. /*******************************************************************
  240. set the share mode of a file
  241. ********************************************************************/
  242. BOOL set_share_mode(int fnum,int mode)
  243. {
  244.   pstring fname;
  245.   int fd2;
  246.   char buf[16];
  247.   int pid = (int)getpid();
  248.  
  249.   if (!share_name_fnum(fnum,fname)) return(False);
  250.  
  251.   {
  252.     int old_umask = umask(0);
  253.     fd2 = open(fname,O_WRONLY|O_CREAT|O_TRUNC,0644);
  254.     umask(old_umask);
  255.   }
  256.   if (fd2 < 0) {
  257.     DEBUG(2,("Failed to create share file %s\n",fname));
  258.     return(False);
  259.   }
  260.  
  261.   SIVAL(buf,0,Files[fnum].open_time);
  262.   SIVAL(buf,4,mode);
  263.   SIVAL(buf,8,pid);
  264.   SIVAL(buf,12,LOCKING_VERSION);
  265.  
  266.   if (write(fd2,buf,16) != 16) {
  267.     close(fd2);
  268.     unlink(fname);
  269.     return(False);
  270.   }
  271.  
  272.   write(fd2,Files[fnum].name,strlen(Files[fnum].name)+1);
  273.  
  274.   close(fd2);
  275.  
  276.   DEBUG(3,("Created share file %s with mode 0x%X pid=%d\n",fname,mode,pid));
  277.  
  278.   return(True);
  279. }
  280.   
  281.  
  282. /*******************************************************************
  283. cleanup any stale share files
  284. ********************************************************************/
  285. void clean_share_files(void)
  286. {
  287.   char *lockdir = lp_lockdir();
  288.   void *dir;
  289.   char *s;
  290.  
  291.   if (!*lockdir) return;
  292.  
  293.   dir = opendir(lockdir);
  294.   if (!dir) return;
  295.  
  296.   while ((s=readdirname(dir))) {
  297.     char buf[16];
  298.     int pid;
  299.     int fd;
  300.     pstring lname;
  301.     int dev,inode;
  302.  
  303.     if (sscanf(s,"share.%d.%d",&dev,&inode)!=2) continue;
  304.  
  305.     strcpy(lname,lp_lockdir());
  306.     trim_string(lname,NULL,"/");
  307.     strcat(lname,"/");
  308.     strcat(lname,s);
  309.  
  310.     fd = open(lname,O_RDONLY,0);
  311.     if (fd < 0) continue;
  312.  
  313.     if (read(fd,buf,16) != 16) {
  314.       close(fd);
  315.       if (!unlink(lname))
  316.     printf("Deleted corrupt share file %s\n",s);
  317.       continue;
  318.     }
  319.     close(fd);
  320.  
  321.     pid = IVAL(buf,8);
  322.  
  323.     if (IVAL(buf,12) != LOCKING_VERSION || !process_exists(pid)) {
  324.       if (!unlink(lname))
  325.     printf("Deleted stale share file %s\n",s);
  326.     }
  327.   }
  328.  
  329.   closedir(dir);
  330. }
  331.